package com.itestor.iptv.global.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

/**
 * 基于spring的泛型DAO实现.
 * @author liwp.
 * @param <T>
 * @param <ID>
 */
public class GenericHibernateDao<T, ID extends Serializable> extends HibernateDaoSupport {

	/**
	 * 实体Class.
	 */
	private final Class<T> entityClass;

	/**
	 * 构造函数，确定实体类型.
	 */
	@SuppressWarnings("unchecked")
	public GenericHibernateDao() {
		this.entityClass = (Class<T>) getGeneric(getClass());
	}

	/**
	 * @return the entityClass
	 */
	public Class<T> getEntityClass() {
		return entityClass;
	}

	/**
	 * 按ID返回实体对象.
	 * @param id 实体ID.
	 * @return T 按返回实体。
	 */
	@SuppressWarnings("unchecked")
	public T find(ID id) {
		return (T) getSession().get(entityClass, id);
	}

	/**
	 * 返回全部的实体对象.
	 * @return List 返回关于T的LIST.
	 */
	@SuppressWarnings("unchecked")
	public Collection<T> findAll() {
		return (Collection<T>) getSession().createCriteria(entityClass).list();
	}

	/**
	 * 返回全部的实体对象.
	 * @return List 返回关于T的LIST.
	 */
	public int count() {
		return getSession().createCriteria(entityClass).list().size();
	}

	/**
	 * 插入新的实体对象.
	 * @param entity 需要保存的实体对象.
	 */
	public void create(T entity) {
		Session session = getSession();
		session.save(entity);
		session.flush();
	}

	/**
	 * 按ID删除相应的实体对象.
	 * @param entityId 实体对象ID编号.
	 */
	public void delete(ID entityId) {
		if (null != find(entityId)) {
			delete(find(entityId));
		}
	}

	/**
	 * 删除相应的实体对象.
	 * @param entity 需要保存的实体对象.
	 */
	public void delete(T entity) {
		Session session = getSession();
		session.delete(entity);
		session.flush();
	}

	/**
	 * 按ID修改相应的实体对象.
	 * @param entity 需要修改的实体对象.
	 */
	public void update(T entity) {
		Session session = getSession();
		session.merge(entity);
		session.flush();
	}

	/**
	 * 判断实体是否存在.
	 * @param query query
	 * @return T 实体对象
	 */
	@SuppressWarnings("unchecked")
	public T getEntity(Query query) {
		if (query.list().iterator().hasNext()) {
			return (T) query.list().iterator().next();
		} else {
			return null;
		}
	}

	/**
	 * @return Session
	 */
	public Session getHibernateSession() {
		return getSession();
	}

	/**
	 * 获取对象类型.
	 * @param entityClass 具体要获取的对象类型
	 * @return Class Class
	 */
	@SuppressWarnings("unchecked")
	private static Class getGeneric(Class entityClass) {
		return getGeneric(entityClass, 1);
	}

	/**
	 * 获取对象类型.
	 * @param entityClass 具体要获取的对象类型
	 * @param index 参数位置
	 * @return Class Class
	 */
	@SuppressWarnings("unchecked")
	private static Class getGeneric(Class entityClass, int index) {
		Type genType = (Type) entityClass.getGenericSuperclass();

		if (genType instanceof ParameterizedType) {
			Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

			if ((params != null) && (params.length >= index)) {
				return (Class) params[index - 1];
			}
		}
		return null;
	}
}
